﻿using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;

namespace System;

/// <summary>
/// 所有对象的扩展方法
/// </summary>
public static class ObjectExtensions
{
    /// <summary>
    /// 用于简化并优化将一个对象强制转换为某种类型的操作
    /// </summary>
    /// <typeparam name="T">要进行强制转换的类型</typeparam>
    /// <param name="obj">要转换的对象</param>
    /// <returns>转换后的对象</returns>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T As<T>(this object obj)
        where T : class
    {
        return (T)obj;
    }

    /// <summary>
    /// 使用 <see cref="Convert.ChangeType(object,System.Type)"/> 方法将给定的对象转换为值类型
    /// </summary>
    /// <param name="obj">要转换的对象</param>
    /// <typeparam name="T">目标对象的类型</typeparam>
    /// <returns>转换后的对象</returns>
    public static T To<T>(this object obj)
        where T : struct
    {
        if (typeof(T) == typeof(Guid))
        {
            return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(obj.ToString()!)!;
        }

        return (T)Convert.ChangeType(obj, typeof(T), CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// 检查一个项目是否在列表中
    /// </summary>
    /// <param name="item">要检查的项目</param>
    /// <param name="list">项目列表</param>
    /// <typeparam name="T">项目类型</typeparam>
    public static bool IsIn<T>(this T item, params T[] list)
    {
        return list.Contains(item);
    }

    /// <summary>
    /// 检查一个项目是否在给定的可枚举对象中
    /// </summary>
    /// <param name="item">要检查的项目</param>
    /// <param name="items">项目</param>
    /// <typeparam name="T">项目类型</typeparam>
    public static bool IsIn<T>(this T item, IEnumerable<T> items)
    {
        return items.Contains(item);
    }

    /// <summary>
    /// 可用于有条件地对一个对象执行某个函数，然后返回修改后的对象或原始对象
    /// 这在链式调用中很有用
    /// </summary>
    /// <param name="obj">一个对象</param>
    /// <param name="condition">一个条件</param>
    /// <param name="func">一个仅在条件为<code>true</code>时才会被执行的函数</param>
    /// <typeparam name="T">对象的类型</typeparam>
    public static T If<T>(this T obj, bool condition, Func<T, T> func)
    {
        if (condition)
        {
            return func(obj);
        }

        return obj;
    }

    /// <summary>
    /// 可用于有条件地对一个对象执行某个函数，然后返回修改后的对象或原始对象
    /// 这在链式调用中很有用
    /// </summary>
    /// <param name="obj">一个对象</param>
    /// <param name="condition">一个条件</param>
    /// <param name="func">一个仅在条件为<code>true</code>时才会被执行的函数</param>
    /// <typeparam name="T">对象的类型</typeparam>
    /// <returns>
    /// Returns the original object.
    /// </returns>
    public static T If<T>(this T obj, bool condition, Action<T> action)
    {
        if (condition)
        {
            action(obj);
        }

        return obj;
    }
}
